package org.totoro.servlet.methodpath.focus;

import org.totoro.servlet.methodpath.annotation.Controller;
import org.totoro.servlet.methodpath.annotation.RequestMp;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author TOTORO
 * @date 2021/5/28 11:50
 */

@MultipartConfig
public class MpServlet extends HttpServlet implements MpMethod {
    private static String status = "200";
    private String serverPath = "localhost:8080";

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        serverPath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort();
        String requestMethod = getRequestMethod(request, response);
        Class useServlet = this.getClass();
        if(!useServlet.isAnnotationPresent(Controller.class)){
            try {
                Method method = useServlet.getMethod("service", HttpServletRequest.class, HttpServletResponse.class);
                return;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        if(POST.equals(requestMethod)){
            doGet(request, response);
        } else if(GET.equals(requestMethod)){
            doPost(request, response);
        } else{
            doGet(request, response);
        }
    }

    /**
     * 获取当前服务器ip端口
     * getCurrentServer ip and port
     * @return
     */
    public String getServerPath(){
        return this.serverPath;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        execution(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        execution(req, resp);
    }

    @Override
    public Method getPathMethod(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String mh = (String) request.getAttribute("method");
        Method method = null;
        Class useServlet = this.getClass();
        // 获取该子类所有的方法
        Method[] methods = useServlet.getMethods();
        // 遍历所有方法，判断方法上的注解是否与Uri传过来的方法相同
        boolean isHave = false;
        for (int i = 0; i < methods.length; i++) {
            // 判断是否有注解
            if(methods[i].isAnnotationPresent(RequestMp.class)){
                // 反射获取注解的value
                RequestMp requestMapper = methods[i].getAnnotation(RequestMp.class);
                // 判断该注解名字是否与Uri上的method相同
                if(requestMapper.value().equals(mh)){
                    isHave = true;
                    method = methods[i];
                    response.setStatus(200);
                    status = "200";
                }
            }
        }
        if(!isHave){
            response.setStatus(404);
            status = "404";
        }
        return method;
    }

    @Override
    public String getRequestMethod(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Method method = getPathMethod(request, response);
        // 反射获取注解
        RequestMp requestMapper = method.getAnnotation(RequestMp.class);
        return requestMapper.method();
    }

    /**
     * get assign method
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void execution(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
        String mh = (String) request.getAttribute("method");
        if (null == mh || "".equals(mh)){
            throw new RuntimeException("访问路径不能为空！");
        }
        Method method = getPathMethod(request, response);
        try {
            if(status.equals("404")){
                return;
            }
            Object o =method.invoke(this,request,response);
            String rel =String.valueOf(o);
            if (rel.startsWith("@")){
                rel =  rel.substring(1);
                response.sendRedirect(rel);
            }else if(rel.startsWith("$")){
                rel = rel.substring(1);
                System.out.println(rel);
                request.getRequestDispatcher(rel).forward(request,response);
            }else {
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().write(rel);
                response.getWriter().close();
            }

        } catch (IllegalAccessException e) {
            throw new RuntimeException("请求路径方法执行异常！！");
        } catch (InvocationTargetException e) {
            throw new RuntimeException("请求路径方法执行异常！！");
        }
    }
}
